#!/usr/bin/python3
# -*- coding:utf-8 -*-
# @Time   :2021/12/17
# @Author :CJX
# @File   :automatic_cleaning.py

import can
import time
import numpy as np
from Injection_valve import injection_port
from Injection_valve import insert_database
from dox_enquiry import dox_command
from detection_relay_board import di_status
from detection_relay_board import do_status

from sql_insert import sql_insert_err
from sql_insert import sql_insert_suc


def io_status():
    while 1:
        global var1, var2, data_do, data_di  # 类型为list
        global falling_edge, rising_edge
        global di_location, do_location, err_inquiry, var_err_inquiry
        # global edge, l_s_time  # 长按和短按判断，类型为array元素为True/False
        inquiry_do = can.Message(arbitration_id=0x0201, data=[0x01], is_extended_id=False)  # 问询
        bus.send(inquiry_do)  # 0x0201 DO状态 返回513
        message_do = bus.recv(timeout=1)  # 接收数据
        type_id_do = message_do.arbitration_id  # 返回can报文类型
        if type_id_do == 513:
            # time_float1 = message_do.timestamp          # 浮点数时间戳
            # time_date1 = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(float(message_do.timestamp)))  # 转str时间
            # 取回4个字节,预留32通道,bytearray->int->bin(str)->去'0b'->bin->左补32位->反向排列
            data_do = '{:0>32b}'.format(int(bin(int.from_bytes(message_do.data[0:4], "little")).replace('0b', ''), 2))[
                      ::-1]
            # print(data_do, type(data_do))
            if var1 != data_do:  # 差异检测，差异写入数据库
                # write_sql(time_date1, type_id_do, data_do)+++++++++++注意排列顺序有修改
                var1 = data_do  # 给中间值赋新值
                do_location = list(data_do)
        time.sleep(0.1)

        err_inquiry = err_inquiry_function(8) + err_inquiry_function(11) + err_inquiry_function(12) + \
                      err_inquiry_function(23) + err_inquiry_function(24) + \
                      err_inquiry_function(25) + err_inquiry_function(26) + err_inquiry_function(27) + \
                      err_inquiry_function(28) + err_inquiry_function(29)
        # err_inquiry供dox_command函数使用，以免复位报警指令
        inquiry_di = can.Message(arbitration_id=0x0301, data=[0x01], is_extended_id=False)
        bus.send(inquiry_di)  # 0x0301  返回769/0x0301 di状态
        message_di = bus.recv(timeout=1)  # 接收数据
        type_id_di = message_di.arbitration_id  # 返回can报文类型
        if type_id_di == 769:
            # time_float2 = message_di.timestamp          # 浮点数时间戳
            # time_date2 = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(float(message_di.timestamp)))  # 转str时间
            # 取回4个字,预留32通道,bytearray->int->bin(str)->去'0b'->bin->左补32位->反向排列
            data_di = '{:0>32b}'.format(int(bin(int.from_bytes(message_di.data[0:4], "little")).replace('0b', ''), 2))[
                      ::-1]
            # print(data_di, type(data_di))
            if data_di != var2:  # 差异检测，差异写入数据库
                # write_sql(time_date2, type_id_di, data_di)
                for k in range(32):
                    if var2[k] == '0' and data_di[k] == '1':  # 32点上升沿检测,没有检测到不复位
                        edge[0, k] = 1  # 写入边缘检测edge[0]
                        edge[1, k] = 0  # 复位下降沿
                        # time_diff[0, k] = time.time()  # 把时间写入array[0]，上升沿触发时间戳
                    if var2[k] == '1' and data_di[k] == '0':  # 32点下降沿检测,没有检测到不复位
                        edge[1, k] = 1  # 写入边缘检测edge[1]
                        edge[0, k] = 0  # 复位上升沿
                        # time_diff[1, k] = time.time()  # 把时间写入array[1]，下降沿触发时间戳
                    # l_s_time[0, k] = 0 < (time_diff[1, k] - time_diff[0, k]) < 3  # 短脉冲判断
                    # l_s_time[1, k] = 3 < (time_diff[1, k] - time_diff[0, k]) < 10  # 长脉冲判断
                    # print((time_diff[1, k] - time_diff[0, k]))
                var2 = data_di  # 给中间值赋新值
                di_location = list(data_di)  # 字符串转列表输出
                # print('下降沿', edge[1])
                # print('上升沿', edgeerr_inquiry)
                rising_edge = edge[0]
                falling_edge = edge[1]
        time.sleep(0.1)
        if di_location[0:1][0] == '1':
            break


def err_inquiry_function(err_num):  # 供dox_command函数使用，以免复位报警指令
    if do_location[err_num - 1:err_num][0] == "1":
        err_inquiry_num = [err_num]
    else:
        err_inquiry_num = [0]
    return err_inquiry_num


def automatic_cleaning():
    ver = 1  # 1为带自动冲洗，0为不带自动冲洗
    automatic_cleaning_n = 1
    while 1:
        global falling_edge, rising_edge, di_location
        global i2c_40, i2c_41, i2c_42, i2c_43, edge, err_inquiry
        automatic_cleaning_t2 = 0
        automatic_cleaning_t3 = 0
        automatic_cleaning_t4 = 0
        automatic_cleaning_t5 = 0
        automatic_cleaning_t6 = 0
        automatic_cleaning_t8 = 0
        automatic_cleaning_t9 = 0
        automatic_cleaning_t11 = 0

        if di_location[0:1][0] == '0' or di_location[20:21][0] == '1':
            break

        if automatic_cleaning_n == 1:
            print("步骤1")
            sql_insert_suc("自动清洗模式")
            dox_command([0], err_inquiry)  # 复位do
            injection_port(0)  # 切换阀复位,X-0指令
            time.sleep(3)
            if insert_database() == "004d":  # 查询指令
                automatic_cleaning_n = 2
                sql_insert_suc("切换阀初始化位置")
                pass  # 成功
            else:
                sql_insert_err("FX—0切换阀初始化故障")  # 可存入数据库
                dox_command([24], err_inquiry)
                return

        if automatic_cleaning_n == 2:
            print("步骤2")
            dox_command([21], err_inquiry)  # 输出DO21
            dox_command([1, 21], err_inquiry)  # 置位DO1
            while automatic_cleaning_t2 <= 59:
                if di_location[1:2][0] == "1":
                    dox_command([21], err_inquiry)  # 复位DO1
                    automatic_cleaning_n = 3
                    automatic_cleaning_t2 = 70
                    sql_insert_suc('测量成功')
                    pass  # 输出测量状态
                else:
                    automatic_cleaning_t2 = automatic_cleaning_t2 + 1
                    time.sleep(1)
            if automatic_cleaning_t2 > 60 and di_location[1:2][0] == "0":
                sql_insert_err("F-1测量指令故障")  # 可存入数据库
                dox_command([23], err_inquiry)  # 复位DO21,输出do23
                return

        if automatic_cleaning_n == 3:
            print("步骤3")
            while automatic_cleaning_t3 <= 39:  # 延时四十秒每秒检测一次di状态，状态符合就退出循环
                automatic_cleaning_t3 = automatic_cleaning_t3 + 1
                time.sleep(1)
                if di_location[0:1][0] == '0' or di_location[20:21][0] == '1':
                    return
            dox_command([21], err_inquiry)  # 复位DO22
            automatic_cleaning_n = 4

        if di_location[0:1][0] == '0' or di_location[20:21][0] == '1':
            return

        if automatic_cleaning_n == 4:
            print("步骤4")
            while automatic_cleaning_t4 <= 129599:  # 延时36h每秒检测一次di状态，状态符合就退出循环
                automatic_cleaning_t4 = automatic_cleaning_t4 + 1
                time.sleep(1)
                if di_location[0:1][0] == '0' or di_location[20:21][0] == '1':
                    return
            dox_command([22, 21], err_inquiry)  # 输出DO22
            automatic_cleaning_n = 5

        if di_location[0:1][0] == '0' or di_location[20:21][0] == '1':
            return

        if automatic_cleaning_n == 5:
            print("步骤5")
            if ver == 1:  # 进入步骤6
                print("步骤6")
                dox_command([31, 22, 21], err_inquiry)  # 输出DO31
                sql_insert_suc("自动程序，在线冲洗")
                while automatic_cleaning_t5 <= 29:  # 延时30秒每秒检测一次di状态，状态符合就退出循环
                    automatic_cleaning_t5 = automatic_cleaning_t5 + 1
                    time.sleep(1)
                    if di_location[0:1][0] == '0' or di_location[20:21][0] == '1':
                        return
                automatic_cleaning_n = 40
            else:
                automatic_cleaning_n = 40

        if di_location[0:1][0] == '0' or di_location[20:21][0] == '1':
            return

        if automatic_cleaning_n == 40:
            if ver == 0:  # 步骤7
                print("步骤7")
                dox_command([2, 31, 22, 21], err_inquiry)  # 置位DO2
                t = 0
                while t <= 60:
                    if di_location[2:3][0] == "1":
                        dox_command([31, 22, 21], err_inquiry)  # 复位DO2
                        injection_port(3)  # x-3指令
                        time.sleep(3)
                        if insert_database() == "034d":  # 查询指令
                            automatic_cleaning_n = 6
                            sql_insert_suc("切换阀水冲洗位置")
                            pass  # 成功
                        else:
                            sql_insert_err("FX-3切换阀水冲洗位故障")  # 可存入数据库f-3
                            dox_command([24], err_inquiry)
                            return 
                        t = 70
                        pass  # 输出检修状态
                    else:
                        time.sleep(1)
                        t = t + 1
                if t > 60 and di_status(3) == "0":
                    sql_insert_err("F-2检修指令故障")  # 输出检修动作故障
                    dox_command([23], err_inquiry)
                    return

        if di_location[0:1][0] == '0' or di_location[20:21][0] == '1':
            return

        if automatic_cleaning_n == 6:  # 步骤8
            print("步骤8")
            dox_command([3, 22, 21], err_inquiry)  # 复位DO31,输出DO3
            while automatic_cleaning_t6 <= 24:  # 延时25秒每秒检测一次di状态，状态符合就退出循环
                automatic_cleaning_t6 = automatic_cleaning_t6 + 1
                time.sleep(1)
                if di_location[0:1][0] == '0' or di_location[20:21][0] == '1':
                    return
            automatic_cleaning_n = 7

        if di_location[0:1][0] == '0' or di_location[20:21][0] == '1':
            return

        if automatic_cleaning_n == 7:  # 步骤9
            print("步骤9")
            dox_command([22, 21], err_inquiry)  # 复位DO3
            injection_port(2)  # x-2指令
            time.sleep(3)
            if insert_database() == "024d":  # 查询指令
                automatic_cleaning_n = 8
                sql_insert_suc("切换阀清洗位置")
                pass  # 成功
            else:
                sql_insert_err("FX-2切换阀清洗位故障")  # 可存入数据库fx-2
                dox_command([24], err_inquiry)
                return

        if di_location[0:1][0] == '0' or di_location[20:21][0] == '1':
            return

        if automatic_cleaning_n == 8:  # 步骤10
            print("步骤10")
            dox_command([4, 22, 21], err_inquiry)  # 输出DO4

            while automatic_cleaning_t8 <= 7:  # 延时8秒每秒检测一次di状态，状态符合就退出循环
                automatic_cleaning_t8 = automatic_cleaning_t8 + 1
                time.sleep(1)
                if di_location[0:1][0] == '0' or di_location[20:21][0] == '1':
                    return

            automatic_cleaning_n = 9

        if di_location[0:1][0] == '0' or di_location[20:21][0] == '1':
            return

        if automatic_cleaning_n == 9:  # 步骤11
            print("步骤11")
            dox_command([22, 21], err_inquiry)  # 复位DO4

            while automatic_cleaning_t9 <= 299:  # 延时5分钟每秒检测一次di状态，状态符合就退出循环
                automatic_cleaning_t9 = automatic_cleaning_t9 + 1
                time.sleep(1)
                if di_location[0:1][0] == '0' or di_location[20:21][0] == '1':
                    return
            automatic_cleaning_n = 10

        if di_location[0:1][0] == '0' or di_location[20:21][0] == '1':
            return

        if automatic_cleaning_n == 10:  # 步骤12
            print("步骤12")
            injection_port(3)  # x-3指令
            time.sleep(3)
            if insert_database() == "034d":  # 查询指令
                automatic_cleaning_n = 11
                sql_insert_suc("切换阀水冲洗位置")
                pass  # 成功
            else:
                sql_insert_err("FX-3切换阀水冲洗位故障")  # 可存入数据库fx-3
                dox_command([24], err_inquiry)
                return

        if di_location[0:1][0] == '0' or di_location[20:21][0] == '1':
            return

        if automatic_cleaning_n == 11:  # 步骤13
            print("步骤13")
            dox_command([3, 22, 21], err_inquiry)  # 输出DO3

            while automatic_cleaning_t11 <= 24:  # 延时24秒每秒检测一次di状态，状态符合就退出循环
                automatic_cleaning_t11 = automatic_cleaning_t11 + 1
                time.sleep(1)
                if di_location[0:1][0] == '0' or di_location[20:21][0] == '1':
                    return
            automatic_cleaning_n = 12

        if di_location[0:1][0] == '0' or di_location[20:21][0] == '1':
            return

        if automatic_cleaning_n == 12:  # 步骤14
            print("步骤14")
            dox_command([22, 21], err_inquiry)  # 复位DO3
            injection_port(0)  # x-0指令
            time.sleep(3)
            if insert_database() == "004d":  # 查询指令
                automatic_cleaning_n = 13
                sql_insert_suc("切换阀初始化位置")
                pass  # 成功
            else:
                sql_insert_err("FX-0切换阀初始化位置故障")  # 可存入数据库fx-0
                dox_command([24], err_inquiry)
                return

        if di_location[0:1][0] == '0' or di_location[20:21][0] == '1':
            return

        if automatic_cleaning_n == 13:  # 步骤15
            print("步骤15")
            # if di_location[10:11][0] == "1":
            #     automatic_cleaning_n = 16
            #     pass  # 预留一个长效计数器作为C1, C1用处就是计算清洗次数，鉴于计数时间较长，建议存到数据库,每次到这+1
            #     C1 = 21  # 测试用
            # else:
            automatic_cleaning_n = 30

        # if automatic_cleaning_n == 16:  # 步骤16
        #     print("步骤16")
        #     if C1 >= 20:
        #         n = 17
        #     else:
        #         n = 30
        #
        # if automatic_cleaning_n == 17:  # 步骤17
        #     print("步骤17")
        #     injection_port(1)
        #     time.sleep(2)
        #     if insert_database() == "014d":  # 查询指令
        #         time.sleep(2)  # 延时两秒
        #         automatic_cleaning_n = 18
        #         pass  # 成功
        #     else:
        #         print("切换阀缓冲液4故障")  # 可存入数据库fx-1
        #
        # if automatic_cleaning_n == 18:  # 步骤18
        #     print("步骤18")
        #     dox_command([13, 22, 21], err_inquiry)  # 输出DO13
        #     time.sleep(15)
        #     automatic_cleaning_n = 19
        #
        # if automatic_cleaning_n == 19:  # 步骤19
        #     print("步骤19")
        #     dox_command([22, 21], err_inquiry)  # 复位DO13
        #     time.sleep(30)
        #     automatic_cleaning_n = 20
        #
        # if automatic_cleaning_n == 20:  # 步骤20
        #     print("步骤20")
        #     # 暂时没法写校准指令，无反馈
        #     # c2 = 1
        #     automatic_cleaning_n = 21
        #
        # if automatic_cleaning_n == 21:  # 步骤21
        #     print("步骤21")
        #     # 读反馈指令
        #     # if 正常 :
        #     #     n = 23
        #     # elif 不正常 and c2 < 2:
        #     #     n = 17
        #     # elif 不正常 and c2 > 2:
        #     #     # 输出故障f——JZ1
        #     #     n = 29
        #     automatic_cleaning_n = 23
        #
        # if automatic_cleaning_n == 23:  # 步骤23
        #     print("步骤23")
        #     C2 = 0
        #     injection_port(4)
        #     time.sleep(2)
        #     if insert_database() == "044d":  # 查询指令
        #         time.sleep(2)  # 延时两秒
        #         automatic_cleaning_n = 24
        #         pass  # 成功
        #     else:
        #         print("切换阀缓冲液6故障")  # 可存入数据库fx-4
        #
        # if automatic_cleaning_n == 24:
        #     print("步骤24")
        #     dox_command([14, 22, 21], err_inquiry)  # 输出DO14
        #     time.sleep(15)
        #     automatic_cleaning_n = 25
        #
        # if automatic_cleaning_n == 25:
        #     print("步骤25")
        #     dox_command([22, 21], err_inquiry)  # 复位DO14
        #     time.sleep(15)
        #     automatic_cleaning_n = 26
        #
        # if automatic_cleaning_n == 26:
        #     print("步骤26")
        #     # ph6校准指令，c2+1
        #     automatic_cleaning_n = 27
        #
        # if automatic_cleaning_n == 27:
        #     print("步骤27")
        #     # 读反馈指令
        #     # if 正常 :
        #     #     n = 29
        #     # elif 不正常 and c2<2:
        #     #     n =23
        #     # elif 不正常 and c2>2:
        #     #     输出故障F——JZ2
        #     #     n = 29
        #     automatic_cleaning_n = 29
        #
        # if automatic_cleaning_n == 29:
        #     print("步骤29")
        #     # 复位c1 c2
        #     automatic_cleaning_n = 30

        if automatic_cleaning_n == 30:
            automatic_cleaning_n = 2
            print("步骤30")
